<template>
  <div>
    <el-row>
      <el-col :xs="24" :md="20">
        
        <div class="filter-input">
          <!-- tag -->
          <el-popover
            v-for="(tag, i) in tags"
            :key="i"
            width="160"
            v-model="visible.condition_change[i]"
            ref="changepopover"
            trigger="click"
            @show="change_condition_setup(tag)"
          >
            <el-form>
              <el-form-item>
                <el-select size="mini" v-model="condition.name" @change="onConditionNameChange">
                  <el-option
                    size="mini"
                    v-for="(m, i) in mappings"
                    :key="i"
                    :value="i"
                    :label="m.name"
                  ></el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-select size="mini" v-model="condition.operator">
                  <el-option
                    size="mini"
                    v-for="(op, i) in condition.selected_mapping.operators || condition.default_mapping.operators"
                    :key="i"
                    :value="op"
                  ></el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-select
                  v-if="condition.selected_mapping.type === 'select'"
                  size="mini"
                  v-model="condition.value"
                >
                  <template
                    v-if="condition.selected_mapping.options.selections.hasOwnProperty('length')"
                  >
                    <!-- options.selections字段是数组 -->
                    <el-option
                      size="mini"
                      v-for="(s, i) in condition.selected_mapping.options.selections"
                      :key="i"
                      :value="s"
                    ></el-option>
                  </template>
                  <template v-else>
                    <!-- options.selections字段是对象，比较复杂的场景 -->
                    <el-option
                      size="mini"
                      v-for="(v, k) in condition.selected_mapping.options.selections"
                      :key="k"
                      :value="k"
                    ></el-option>
                  </template>
                </el-select>
                <el-date-picker
                  v-else-if="condition.selected_mapping.type === 'date'"
                  v-model="condition.value_date"
                  style="max-width: 135px;"
                  :width="60"
                  size="mini"
                  type="month"
                  :default-value="null"
                  placeholder="选择月">
                </el-date-picker>
                <el-input v-else size="mini" v-model="condition.value"></el-input>
              </el-form-item>
            </el-form>
            <div style="text-align: right margin: 0">
              <el-button type="danger" size="mini" @click="tags.splice(i, 1); visible.condition_change[i]=false">删除</el-button>
              <el-button type="primary" size="mini" @click="change_condition(i)">确定</el-button>
            </div>
            <el-tag slot="reference">{{ tag.name+' '+tag.operator+' '+tag.value }}</el-tag>
          </el-popover>
          
          <el-popover width="160" size="mini" v-model="visible.condition">
            <el-form>
              <el-form-item>
                <el-select size="mini" v-model="condition.name" @change="onConditionNameChange">
                  <el-option
                    size="mini"
                    v-for="(m, i) in mappings"
                    :key="i"
                    :value="i"
                    :label="m.name"
                  ></el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-select size="mini" v-model="condition.operator">
                  <el-option
                    size="mini"
                    v-for="(op, i) in condition.selected_mapping.operators || condition.default_mapping.operators"
                    :key="i"
                    :value="op"
                  ></el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-select
                  v-if="condition.selected_mapping.type === 'select'"
                  size="mini"
                  v-model="condition.value"
                >
                  <template
                    v-if="condition.selected_mapping.options.selections.hasOwnProperty('length')"
                  >
                    <!-- options.selections字段是数组 -->
                    <el-option
                      size="mini"
                      v-for="(s, i) in condition.selected_mapping.options.selections"
                      :key="i"
                      :value="s"
                    ></el-option>
                  </template>
                  <template v-else>
                    <!-- options.selections字段是对象，比较复杂的场景 -->
                    <el-option
                      size="mini"
                      v-for="(v, k) in condition.selected_mapping.options.selections"
                      :key="k"
                      :value="k"
                    ></el-option>
                  </template>
                </el-select>
                <el-date-picker
                  v-else-if="condition.selected_mapping.type === 'date'"
                  v-model="condition.value_date"
                  style="max-width: 135px;"
                  :width="60"
                  size="mini"
                  type="month"
                  placeholder="选择月">
                </el-date-picker>
                <el-input v-else size="mini" v-model="condition.value"></el-input>
              </el-form-item>
            </el-form>
            <div style="text-align: right margin: 0">
              <el-button type="primary" size="mini" @click="create_condition()">确定</el-button>
            </div>
            <el-button slot="reference" type="text" size="mini" style="margin-left: .6rem">添加筛选条件</el-button>
          </el-popover>
          <el-popover width="160" v-model="visible.clear_all">
            <p>全部清除？</p>
            <div style="text-align: right; margin: 0">
              <el-button type="danger" size="mini" @click="visible.clear_all=false; tags=[]">确定</el-button>
            </div>
            <el-button
              v-show="tags.length > 0"
              slot="reference"
              type="text"
              size="mini"
              style="margin-left: .3rem; color: red"
            >清除</el-button>
          </el-popover>
        </div>
      </el-col>
      <el-col :md="4">
        <span style="light-height: 1.6rem">结果：{{ this.filtered_data.length }}个</span>
      </el-col>
    </el-row>
    <slot name="data-table" :data="filtered_data"></slot>
  </div>
</template>

<script>
export default {
  name: "FilterInput",
  componentName: "FilterInput",
  props: ["data", "mappings"],
  data() {
    return {
      filters: [], // [func(data-tables), ...]
      tags: [], // [{mapping, name, operator, value, value_map}, ...]
      condition: {
        default_mapping: {
          type: "text",
          operators: ["=", ">", ">=", "<", "<=", "!="],
          compareFunc(a, op, b) {
            // 依次对指定列的值a用op与条件中的b做比较，返回true/false
            switch (op) {
              case "=":
                return a === b
              case ">":
                return a > b
              case ">=":
                return a >= b
              case "<":
                return a < b
              case "<=":
                return a <= b
              case "!=":
                return a !== b
              default:
                return false
            }
          },
        },
        selected_mapping: {},
        name: "",
        operator: "",
        value: "",
        value_date: Date(),
      },
      visible: {
        condition_change: [],
        condition: false,
      },
      filtered_data: [],
    }
  },
  watch: {
    tags() {
      // 筛选条件发生变化
      console.log("tags change")
      this.storeTags()
      let temp_data = []
      for (let i = 0; i < this.data.length; i++) {
        let valid = true
        for (let tag of this.tags) {
          let a = this.data[i][tag.mapping.field]
          let op = tag.operator
          let b = tag.value_map
          let cmpFunc =
            tag.mapping.compareFunc ||
            this.condition.default_mapping.compareFunc
          if (!cmpFunc(a, op, b, this.condition.default_mapping.compareFunc)) {
            // 传入default compareFunc，给自定义compareFunc一个调用的机会
            valid = false
            break
          } else {
            valid = true
          }
        }
        if (valid) {
          temp_data.push(this.data[i])
        }
        
      }
      this.filtered_data = temp_data
    },
    data() {
      // 数据源更新，可判断为初始化
      this.filtered_data = this.data
      this.recoverTags()
    },
    "condition.value_date": function() {
      // 日期选择器改变
      this.condition.value = this.condition.value_date.toISOString().split("T")[0]
    }
  },
  methods: {
    create_condition() {
      // let name = this.condition.name
      let operator = this.condition.operator
      let value = this.condition.value
      if (value === "") {
        this.$message("值不能为空")
      } else {
        this.tags.push({
          mapping: this.condition.selected_mapping,
          name: this.condition.selected_mapping.name,
          operator,
          value,
          value_map: function (value) {
            if (this.condition.selected_mapping.type === "select") {
              if (!this.condition.selected_mapping.options.selections.length) {
                // 需要映射选项
                return this.condition.selected_mapping.options.selections[
                  value
                ]
              }
            }
            return value
          }.call(this, value),
        })
        this.visible.condition = false
      }
    },

    change_condition_setup(tag) {
      this.condition.selected_mapping = tag.mapping
      this.condition.name = tag.name
      this.condition.operator = tag.operator
      this.condition.value = tag.value
    },

    change_condition(i) {
      let tag = this.tags[i]
      let operator = this.condition.operator
      let value = this.condition.value
      if (value === "") {
        this.$message("值不能为空")
      } else {
        this.$set(this.tags, this.tags.indexOf(tag), {
          mapping: this.condition.selected_mapping,
          name: this.condition.selected_mapping.name,
          operator,
          value,
          value_map: function (value) {
            if (this.condition.selected_mapping.type === "select") {
              if (!this.condition.selected_mapping.options.selections.length) {
                // 需要映射选项
                return this.condition.selected_mapping.options.selections[
                  value
                ]
              }
            }
            return value
          }.call(this, value),
        })
        this.$set(this.visible.condition_change, i, false)
      }
    },

    onConditionNameChange(i) {
      this.condition.selected_mapping = this.mappings[i]
      console.log(this.condition.selected_mapping)
    },

    storeTags() {
      // 保存tags到本地存储
      localStorage.setItem("filter_input_tags", JSON.stringify((function(){
        let items = []
        for (let tag of this.tags) {
          items.push({
            mapping_name: tag.mapping.name,
            name: tag.name,
            operator: tag.operator,
            value: tag.value,
            value_map: tag.value_map,
          })
        }
        return items
      }).call(this)))
    },

    recoverTags() {
      // 从本地存储中恢复tags
      let temp_data = []
      let tags = localStorage.getItem("filter_input_tags")
      if (! tags) {
        return
      }
      tags = JSON.parse(tags)
      for (let tag of tags) {
        // 从已知mapping中寻找同名的mapping，作为匹配相同的唯一条件
        for (let mapping of this.mappings) {
          if (tag.mapping_name === mapping.name) {
            temp_data.push({
              mapping,
              name: tag.name,
              operator: tag.operator,
              value: tag.value,
              value_map: tag.value_map,
            })
            break
          }
        }
      }
      this.tags = temp_data
    },
  },
}
</script>

<style scoped>
.filter-input {
  display: flex;
  justify-content: left;
  padding: 0.3rem;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.filter-input > * {
  margin-right: 0.3rem
}

.close {
  margin-left: 5px;
  font-size: 1rem;
  line-height: inherit
}

.el-tag:hover {
  cursor: pointer
}
</style>